home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / pascal / sthing.com / STRES.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1990-10-28  |  12.6 KB  |  495 lines

  1. {
  2.   STRES is a memory resident program for reading text screens and speaking
  3.   them via the Covox Speech Thing. Before loading STRES you must first load
  4.   SPEECHV2 or SPEECHV3. Note that it is *not* necessary to load Covox's STALK
  5.   memory resident program.
  6.  
  7.   Type STRES /? for a summary of options and commands.
  8.  
  9.   A dictionary file is an ASCII text file with one definition per line. A
  10.   definition is the normal text spelling of a word followed by one or more
  11.   spaces, followed by the phonetic spelling of the word using the SmoothTalker
  12.   phonetic codes (see Appendix A of the Speech Thing User Manual). Lines that
  13.   begin with a semicolon are treated as comments. Here's an example of a valid
  14.   dictionary file:
  15.  
  16. ;these entries just encode the standard pronunciations
  17. ARBITRARILY    AArbIXtrEHr4IXl3IY
  18. ARBITRATOR     AArbIXtr4EYDX3ER
  19. COMPUTER       kAXmpy4UWDX3ER
  20. DICTIONARY     dIHkSHAXn4EHr3IY
  21.  
  22.   Whenever STRES reads one of the words in the first column of the dictionary
  23.   file, SmoothTalker pronounces it as specified by the phonetics of the second
  24.   column.
  25.  
  26.   STRES.PAS requires TurboPower Software's Object Professional library (a
  27.   commercial product) to compile. STRES.EXE is provided in this same archive.
  28.  
  29.   Written 10/90 by Kim Kokkonen, TurboPower Software
  30.   Copyright (C) 1990, TurboPower Software. All rights reserved.
  31. }
  32.  
  33. {$S-,I-,R-,V-,F-}
  34. {$M 2048,0,655360}
  35.  
  36. program StRes;
  37.   {-Resident interface to Speech Thing}
  38.  
  39. uses
  40.   sthing, opinline, dos, opstring, opcrt, opint, optsr;
  41.  
  42. const
  43.   modulename : string[5] = 'STRES';
  44.   version = '1.00';
  45.   screenhotkey   = $051F; {Ctrl-RShift-S}
  46.   readerhotkey = $0513;   {Ctrl-RShift-R}
  47.   waitfordos = false;
  48.   speakit : boolean = false;
  49.  
  50. procedure message(s : string);
  51. begin
  52.   writeln(s);
  53.   if SpeakIt then
  54.     stspeak(s);
  55. end;
  56.  
  57. procedure clearkbd;
  58.   {-clear keyboard buffer}
  59. var
  60.   ch : char;
  61. begin
  62.   while keypressed do
  63.     ch := readkey;
  64. end;
  65.  
  66. var
  67.   st : string;
  68.  
  69. function CharToWord(Ch : Char) : String;
  70.   {-Return speakable string for character}
  71. var
  72.   St : String[39];
  73. begin
  74.   Ch := UpCase(Ch);
  75.   case Ch of
  76.     #32 : St := ' space';
  77.     '!' : St := ' point';
  78.     ',' : St := 'comma';
  79.     '.' : St := 'period';
  80.     ':' : St := 'colon';
  81.     ';' : St := ' semicolon';
  82.     '\' : St := 'backslash';
  83.     '-' : St := ' dash';
  84.     '[' : St := 'open bracket';
  85.     ']' : St := 'close bracket';
  86.     #39 : St := 'apostrofee';
  87.     'A' : St := '~S9 EY';
  88.     'K' : St := ' kay';
  89.     'Q' : St := ' cue';
  90.     'W' : St := 'S95'+Ch;
  91.     'Z' : St := ' zzzzee';
  92.   else
  93.     St := 'S9 '+Ch;
  94.   end;
  95.   CharToWord := '<<'+St+'>>';
  96. end;
  97.  
  98. procedure readst(y : byte);
  99. begin
  100.   fastread(screenwidth, y, 1, st);
  101.   st := trimtrail(st);
  102. end;
  103.  
  104. procedure speakline(y, x1, x2 : byte);
  105. begin
  106.   gotoxy(x1, y);
  107.   if x2 = x1 then begin
  108.     {spell character}
  109.     if x1 > length(st) then
  110.       stspeak(' ')
  111.     else
  112.       stspeak(chartoword(st[x1]));
  113.   end else
  114.     stspeak(copy(st, x1, x2-x1+1));
  115. end;
  116.  
  117. procedure posspeak(x, y : byte; msg : string);
  118. begin
  119.   gotoxy(x, y);
  120.   stspeak(msg);
  121. end;
  122.  
  123. {$F+}
  124. procedure readscreen(var regs : registers);
  125.   {-read portions of the screen based on cursor movements}
  126. var
  127.   row : word;
  128.   xy : word;
  129.   sl : word;
  130.   x : byte;
  131.   y : byte;
  132.   kw : word;
  133.   done : boolean;
  134.   e : byte;
  135. begin
  136.   reinitcrt;
  137.   if not intextmode then begin
  138.     stspeak(' not in text mode');
  139.     exit;
  140.   end;
  141.   getcursorstate(xy, sl);
  142.   stgrabint7e;
  143.   clearkbd;
  144.   blockcursor;
  145.  
  146.   y := hi(xy);
  147.   x := lo(xy);
  148.   fastread(screenwidth, y, 1, st);
  149.  
  150.   done := false;
  151.   repeat
  152.     kw := readkeyword;
  153.     case kw of
  154.       $4800 : {Up}
  155.         if y > 1 then begin
  156.           dec(y);
  157.           readst(y);
  158.           speakline(y, x, screenwidth);
  159.         end else
  160.           stspeak(' top of screen');
  161.  
  162.       $5000 : {Down}
  163.         if y < screenheight then begin
  164.           inc(y);
  165.           readst(y);
  166.           speakline(y, x, screenwidth);
  167.         end else
  168.           stspeak(' bottom of screen');
  169.  
  170.       $4B00 : {Left}
  171.         if x > 1 then begin
  172.           dec(x);
  173.           speakline(y, x, x);
  174.         end else
  175.           stspeak(' left of screen');
  176.  
  177.       $7300 : {CtrlLeft}
  178.         if length(st) <> 0 then begin
  179.           if x = 1 then
  180.             stspeak(' left of screen')
  181.           else begin
  182.             {scan to next word left}
  183.             if st[x] <> ' ' then begin
  184.               {currently within a word}
  185.               dec(x);
  186.               if st[x] = ' ' then
  187.                 {go to end of previous word}
  188.                 while (x > 0) and (st[x] = ' ') do
  189.                   dec(x);
  190.               {go to beginning of this word}
  191.               while (x > 0) and (st[x] <> ' ') do
  192.                 dec(x);
  193.               inc(x);
  194.             end else begin
  195.               {currently between words}
  196.               {go to end of previous word}
  197.               while (x > 0) and (st[x] = ' ') do
  198.                 dec(x);
  199.               if (x <> 0) then
  200.                 {go to begin of previous word}
  201.                 while (x > 0) and (st[x] <> ' ') do
  202.                   dec(x);
  203.               inc(x);
  204.             end;
  205.  
  206.             {find end of word}
  207.             e := x;
  208.             while (e <= length(st)) and (st[e] <> ' ') do
  209.               inc(e);
  210.             dec(e);
  211.  
  212.             speakline(y, x, e);
  213.           end;
  214.         end else begin
  215.           x := 1;
  216.           posspeak(x, y, ' left of screen');
  217.         end;
  218.  
  219.       $4D00 : {Right}
  220.         if x < screenwidth then begin
  221.           inc(x);
  222.           speakline(y, x, x);
  223.         end else
  224.           stspeak(' right of screen');
  225.  
  226.       $7400 : {CtrlRight}
  227.         if length(st) <> 0 then begin
  228.           if x = screenwidth then
  229.             stspeak(' right of screen')
  230.           else begin
  231.             {scan to next word right}
  232.             if st[x] <> ' ' then begin
  233.               {currently within a word}
  234.               while (x <= length(st)) and (st[x] <> ' ') do
  235.                 inc(x);
  236.               if (x <= length(st)) then begin
  237.                 {skip over spaces after the word}
  238.                 while (x <= length(st)) and (st[x] = ' ') do
  239.                   inc(x);
  240.               end;
  241.             end else begin
  242.               {starting in white space}
  243.               while (x <= length(st)) and (st[x] = ' ') do
  244.                 inc(x);
  245.             end;
  246.  
  247.             if x <= length(st) then begin
  248.               {find end of word}
  249.               e := x;
  250.               while (e <= length(st)) and (st[e] <> ' ') do
  251.                 inc(e);
  252.               dec(e);
  253.               speakline(y, x, e);
  254.             end else
  255.               posspeak(x, y, ' right of screen');
  256.           end;
  257.         end else begin
  258.           x := 1;
  259.           posspeak(x, y, ' right of screen');
  260.         end;
  261.  
  262.       $4700 : {Home}
  263.         begin
  264.           x := 1;
  265.           posspeak(x, y, ' left of screen');
  266.         end;
  267.  
  268.       $4F00 : {End}
  269.         begin
  270.           x := screenwidth;
  271.           posspeak(x, y, ' right of screen');
  272.         end;
  273.  
  274.       $4900 : {PgUp}
  275.         begin
  276.           if y <> 1 then begin
  277.             y := 1;
  278.             readst(y);
  279.           end;
  280.           posspeak(x, y, ' top of screen');
  281.         end;
  282.  
  283.       $5100 : {PgDn}
  284.         begin
  285.           if y <> screenheight then begin
  286.             y := screenheight;
  287.             readst(y);
  288.           end;
  289.           posspeak(x, y, ' bottom of screen');
  290.         end;
  291.  
  292.       $4000, $1C0D, $011B : {F6, Enter, Esc}
  293.         Done := True;
  294.  
  295.     end;
  296.   until done;
  297.  
  298.   clearkbd;
  299.   strestoreint7e;
  300.   restorecursorstate(xy, sl);
  301. end;
  302.  
  303. procedure speakscreen(var regs : registers);
  304.   {-speak the entire screen regardless of cursor position}
  305. var
  306.   row : word;
  307.   xy : word;
  308.   sl : word;
  309. begin
  310.   reinitcrt;
  311.   if not intextmode then begin
  312.     stspeak(' not in text mode');
  313.     exit;
  314.   end;
  315.   getcursorstate(xy, sl);
  316.   stgrabint7e;
  317.   clearkbd;
  318.   blockcursor;
  319.   row := 1;
  320.   while (row <= screenheight) and not keypressed do begin
  321.     gotoxy(1, row);
  322.     readst(row);
  323.     speakline(row, 1, screenwidth);
  324.     inc(row);
  325.   end;
  326.   clearkbd;
  327.   strestoreint7e;
  328.   restorecursorstate(xy, sl);
  329. end;
  330. {$F-}
  331.  
  332. procedure externalifc(bp : word); interrupt;
  333. var
  334.   regs : intregisters absolute bp;
  335.   savepsp : word;
  336. begin
  337.   case char(regs.ah) of
  338.     'U' :
  339.       begin
  340.         savepsp := getpsp;
  341.         regs.al := byte(disabletsr);
  342.         setpsp(savepsp);
  343.       end;
  344.   end;
  345. end;
  346.  
  347. procedure unloadfromcommandline;
  348. var
  349.   regs : intregisters;
  350.   p : ifcptr;
  351. begin
  352.   p := moduleptrbyname(modulename);
  353.   if p = nil then begin
  354.     message(modulename+' not loaded');
  355.     halt;
  356.   end;
  357.   restoreallvectors;
  358.   regs.ah := Byte('U');
  359.   emulateint(regs, p^.cmdentryptr);
  360.   if regs.al = 1 then
  361.     message(modulename+' unloaded')
  362.   else
  363.     message('Unable to unload '+modulename);
  364.   halt;
  365. end;
  366.  
  367. procedure analyzecommandline;
  368. const
  369.   lptnums : string[3] = '123';
  370. var
  371.   i : word;
  372.   status : word;
  373.   lpt : word;
  374.   arg : comstr;
  375.  
  376.   procedure writehelp;
  377.   begin
  378.     st := modulename+', Version ';
  379.     st := st+version;
  380.     st := st+', by TurboPower Software';
  381.     message(st);
  382.     message('Usage:');
  383.     st := '  '+modulename;
  384.     st := st+' [options] [dictionaryfile]';
  385.     message(st);
  386.     message('Command line options:');
  387.     message('  /L lptnum     specify line printer port (1, 2, 3)');
  388.     message('  /S            speak installation messages');
  389.     message('  /U            unload '+modulename+' from memory');
  390.     message('Hot keys:');
  391.     message('  [Ctrl-RightShift-R] for screen reader mode');
  392.     message('  [Ctrl-RightShift-S] to speak whole screen');
  393.     message('Screen reader mode:');
  394.     message('  [Up]          read next line up');
  395.     message('  [Down]        read next line down');
  396.     message('  [Left]        read next character left');
  397.     message('  [Right]       read next character right');
  398.     message('  [Ctrl-Left]   read next word left');
  399.     message('  [Ctrl-Right]  read next word right');
  400.     message('  [Home]        move cursor to left of screen');
  401.     message('  [End]         move cursor to right of screen');
  402.     message('  [PgUp]        move cursor to top of screen');
  403.     message('  [PgDn]        move cursor to bottom of screen');
  404.     message('  [Enter],[Esc] exit from reader mode');
  405.     halt;
  406.   end;
  407.  
  408.   procedure invalidoption;
  409.   begin
  410.     message('Invalid command line option: '+arg);
  411.     writehelp;
  412.   end;
  413.  
  414. begin
  415.   i := 1;
  416.   while i <= paramcount do begin
  417.     arg := stupcase(paramstr(i));
  418.     case arg[1] of
  419.       '/', '-' :
  420.         if length(arg) = 2 then
  421.           case arg[2] of
  422.             '?' : writehelp;
  423.             'L' : if i = paramcount then
  424.                     invalidoption
  425.                   else begin
  426.                     inc(i);
  427.                     arg := stupcase(paramstr(i));
  428.                     if length(arg) <> 1 then
  429.                       invalidoption
  430.                     else begin
  431.                       lpt := pos(arg[1], lptnums);
  432.                       if lpt = 0 then
  433.                         invalidoption
  434.                       else
  435.                         stsetlptport(lpt);
  436.                     end;
  437.                   end;
  438.             'S' : speakit := true;
  439.             'U' : unloadfromcommandline;
  440.           else
  441.             invalidoption;
  442.           end;
  443.     else
  444.       {read dictionary file}
  445.       status := streaddictfile(arg);
  446.       if status <> 0 then begin
  447.         st := long2str(status);
  448.         st := 'Error '+st;
  449.         st := st+' reading ';
  450.         st := st+arg;
  451.         message(st);
  452.         halt;
  453.       end else begin
  454.         st := 'Dictionary '+arg;
  455.         st := st+' loaded';
  456.         message(st);
  457.       end;
  458.     end;
  459.     inc(i);
  460.   end;
  461. end;
  462.  
  463. begin
  464.   if not stloaded then begin
  465.     writeln('SPEECHVx must be loaded first');
  466.     halt;
  467.   end;
  468.  
  469.   if paramcount <> 0 then
  470.     analyzecommandline;
  471.  
  472.   if moduleinstalled(modulename) then begin
  473.     message(modulename+' already installed. Aborting...');
  474.     halt;
  475.   end;
  476.  
  477.   installmodule(modulename, @externalifc);
  478.  
  479.   if definepop(screenhotkey, speakscreen, ptr(sseg, sptr), waitfordos) then
  480.     if definepop(readerhotkey, readscreen, ptr(sseg, sptr), waitfordos) then begin
  481.       st := 'Loading '+modulename;
  482.       st := st+', Version ';
  483.       st := st+version;
  484.       st := st+', by TurboPower Software';
  485.       message(st);
  486.       message('  [Ctrl-RightShift-R] for screen reader mode');
  487.       message('  [Ctrl-RightShift-S] to speak whole screen');
  488.       strestoreint7e;
  489.       popupson;
  490.       stayres(paragraphstokeep, 0);
  491.     end;
  492.  
  493.   message(modulename+' unable to go resident');
  494. end.
  495.